//
//  ViewController.m
//  GCDSocketClient
//
//  Created by chenf on 2022/5/21.
//

#import "ViewController.h"
#import "GCDAsyncSocket.h"
#import "Masonry.h"
#import "SocketManager.h"
#define Image_Command 0x00000001
#define Video_Command 0x00000002
#define Json_Command 0x00000003
#define Text_Command 0x00000004
#define Split_Line_Command 0x00000009

@interface ViewController ()<GCDAsyncSocketDelegate>

@property(nonatomic,strong)GCDAsyncSocket *serverSocket;
@property(nonatomic,strong)UITextField *inputField;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    UIButton *linkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    linkBtn.backgroundColor = UIColor.systemOrangeColor;
    [linkBtn setTitle:@"Start Server" forState:UIControlStateNormal];
    linkBtn.titleLabel.font =[UIFont systemFontOfSize:12];
    [self.view addSubview:linkBtn];
    [linkBtn addTarget:self action:@selector(createSocket) forControlEvents:UIControlEventTouchUpInside];
    
    CGFloat width = 88,gap = 10,left = (UIScreen.mainScreen.bounds.size.width-width*3)/4;
    [linkBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(44);
        make.left.equalTo(self.view).offset(left);
        make.width.mas_equalTo(@(width));
        make.height.mas_equalTo(@(32));
    }];
    UIButton *reconnectBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    reconnectBtn.backgroundColor = UIColor.blueColor;
    [reconnectBtn setTitle:@"ReCon Socket" forState:UIControlStateNormal];
    [self.view addSubview:reconnectBtn];
    reconnectBtn.titleLabel.font =linkBtn.titleLabel.font;
    [reconnectBtn addTarget:self action:@selector(reConnectSocket) forControlEvents:UIControlEventTouchUpInside];
    
    [reconnectBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(linkBtn);
        make.left.equalTo(linkBtn.mas_right).offset(left);
        make.width.height.equalTo(linkBtn);
    }];
    
    
    UIButton *disConnectBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    disConnectBtn.backgroundColor = UIColor.systemOrangeColor;
    [disConnectBtn setTitle:@"DisCon Socket" forState:UIControlStateNormal];
    disConnectBtn.titleLabel.font =linkBtn.titleLabel.font;
    [self.view addSubview:disConnectBtn];
    [disConnectBtn addTarget:self action:@selector(disConnectSocket) forControlEvents:UIControlEventTouchUpInside];
    
    [disConnectBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(linkBtn);
        make.left.equalTo(reconnectBtn.mas_right).offset(left);
        make.width.height.equalTo(linkBtn);
    }];
    
    
    //输入框内容
    self.inputField = [[UITextField alloc] init];
    self.inputField.layer.borderWidth = 2;
    self.inputField.layer.borderColor = [UIColor grayColor].CGColor;
    [self.view addSubview:self.inputField];
    [_inputField mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(linkBtn.mas_bottom).offset(gap);
        make.left.equalTo(linkBtn);
        make.right.equalTo(reconnectBtn.mas_right);
        make.height.mas_equalTo(@(36));
    }];
    //发送消息框
    UIButton *sendBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    sendBtn.backgroundColor = UIColor.blueColor;
    [sendBtn setTitle:@"Send" forState:UIControlStateNormal];
    sendBtn.titleLabel.font =[UIFont systemFontOfSize:10];
    [self.view addSubview:sendBtn];
    [sendBtn addTarget:self action:@selector(sendMessage) forControlEvents:UIControlEventTouchUpInside];
    
    [sendBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_inputField);
        make.left.equalTo(self.inputField.mas_right);
        make.width.mas_equalTo(@(44));
        make.height.mas_equalTo(@(36));
    }];
    //发送图片信息
    UIButton *sendImageBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    sendImageBtn.backgroundColor = UIColor.blueColor;
    [sendImageBtn setTitle:@"SImg" forState:UIControlStateNormal];
    sendImageBtn.titleLabel.font =[UIFont systemFontOfSize:10];
    [self.view addSubview:sendImageBtn];
    [sendImageBtn addTarget:self action:@selector(sendImageMsg) forControlEvents:UIControlEventTouchUpInside];
    
    [sendImageBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(_inputField);
        make.left.equalTo(sendBtn.mas_right).mas_offset(4);
        make.width.mas_equalTo(@(44));
        make.height.mas_equalTo(@(36));
    }];
}
#pragma mark -- 创建socket
-(void)reConnectSocket{
    //创建socket
    if(self.serverSocket == nil){
        [self createSocket];
    }
}
-(void)disConnectSocket{
    [self.serverSocket disconnect];
    self.serverSocket = nil;
    //清除所有链接
    [[SocketManager sharedSocketManager] clearAll];
}
-(void)createSocket{
    //创建Socket
    if(_serverSocket == nil){
        _serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }
    //链接Socket
    NSError *error;
    BOOL result = [self.serverSocket acceptOnPort:9999 error:&error];

    if(result){
        NSLog(@"成功");
    }else{
        NSLog(@"%@",error);
    }
}

#pragma mark -- 重连
//简单发送消息
//复杂内容： 4[总长度] + 4[内容类型] + 发送内容
//Server + Client 约定发送内容协议
-(void)sendMessage{
    if(self.inputField.text.length>0){
        // 直接进行转发数据
        NSArray *existSocket = [SocketManager sharedSocketManager].currentExistSocketes;
        if(existSocket.count>0){
            NSData *data = [self getContentData:[self.inputField.text dataUsingEncoding:NSUTF8StringEncoding] dataType:Text_Command];
            for (GCDAsyncSocket *clientSocket in existSocket) {
                if(clientSocket.isConnected){
                    [clientSocket writeData:data withTimeout:-1 tag:123456];
                }else{
                    NSLog(@"Client is disconnect %@",clientSocket);
                    //移除
                    [[SocketManager sharedSocketManager] removeClicent:clientSocket key:nil];
                }
            }
        }else{
            NSLog(@"No exists Client is connected, donot send message");
        }
    }
    self.inputField.text = @"";
    [self.serverSocket readDataWithTimeout:-1 tag:123456];
}

-(void)sendHeatMsg{
    [self.serverSocket readDataWithTimeout:-1 tag:123456];
}

-(void)sendImageMsg{
    //发送数据
    NSDictionary *existSocketsDict = [SocketManager sharedSocketManager].currentExistRegisterSocketes;
    if(existSocketsDict.count>0){
        //测试能够发送图片数据
        NSData *data = [self getContentData:UIImageJPEGRepresentation( [UIImage imageNamed:@"socketTest.jpg"],1.0) dataType:Image_Command];
        for (NSString *key in existSocketsDict.allKeys) {
            GCDAsyncSocket *clientSocket =existSocketsDict[key];
            if(clientSocket&&clientSocket.isConnected){
                [clientSocket writeData:data withTimeout:-1 tag:123456];
            }else{
                NSLog(@"Client is disconnect %@",clientSocket);
                //移除
                [[SocketManager sharedSocketManager] removeClicent:clientSocket key:key];
            }
        }
    }else{
        NSLog(@"No exists Client is connected, donot send message");
    }
}

-(NSData *)getContentData:(NSData *)data dataType:(unsigned int)dataType{
//    NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
    NSMutableData *dataArray = [NSMutableData data];
    //4+4+内容+"结束表示:\t"
   
    @autoreleasepool {
        unsigned int totoalSize = 4 +4 +(int)data.length+4;
        NSData *totoalSizeData = [NSData dataWithBytes:&totoalSize length:4];
        [dataArray appendData:totoalSizeData];
        unsigned int totalTypeSize = dataType;
        NSData *commImageData = [NSData dataWithBytes:&totalTypeSize length:4];
        [dataArray appendData:commImageData];
        
        [dataArray appendData:data];
        unsigned int splitSize = Split_Line_Command;
        NSData *endData = [NSData dataWithBytes:&splitSize length:4];
        [dataArray appendData:endData];
        
        //最后拼接数据
        NSLog(@"发送数据的总字节大小:%ld",dataArray.length);
        NSLog(@"发送数据内容大小:%ld",data.length);
    }

  return  dataArray;
}

#pragma mark - GCDAsyncSocketDelegate
#pragma mark -- socket 读取与写入数据 代理方法
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"链接成功: %@:%d",host,port);
    //链接成功后，主动读取服务端消息
    [sock readDataWithTimeout:-1 tag:123456];
}
//已经接受客户端发送数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    NSString *content = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];
    NSLog(@"接收成功：tag= %ld:%ld 长度的数据:%@",tag,data.length-1,content);
    //接受到客户端初始化数据的时候，需要记录对应cliect相关信息
    if([content containsString:@"mobileClientInit"]){
        //初始化信息
        //{
//        buss = mobileClientInit;
//        userId = 18011538429;
//    }
        NSDictionary *dict =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
        NSLog(@"%@",dict);
        if(dict[@"userId"]){
            [[SocketManager sharedSocketManager] addClicent:sock userId:dict[@"userId"]];
        }
    }
    [sock readDataWithTimeout:-1 tag:123456];
}
//信息发送成功 代理函数、向服务器 发送信息
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"发送数据成功 tag=:%ld",tag);
    [sock readDataWithTimeout:-1 tag:123456];
}
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"断开 socket链接 原因:%@",err);
    //移除
    [[SocketManager sharedSocketManager] removeClicent:sock key:nil];
}

- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
    //这里需要对Socket的工作原理进行一点解释，当Socket accept一个连接服务请求时，将生成一个新的Socket，即此处的newSocket。在此可查看newSocket.connectedHost和newSocket.connectedPort等参数，并通过新的socket向客户端发送一包数据后会关闭你一开始创建的socket(self.serverSocket),接下来你都将使用newSocket(我将此保存为self.clientSocket)
    NSLog(@"收到链接:%@: %d",[[NSString alloc] initWithData: newSocket.localAddress encoding:NSUTF8StringEncoding], newSocket.localPort);
    [[SocketManager sharedSocketManager] addClicent:newSocket];
    [newSocket readDataWithTimeout:-1 tag:0];
}

@end
